package de.fhkiel.webstore;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.servlet.http.HttpSession;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import de.fhkiel.webservice.ItemService;
import de.fhkiel.webservice.PaymentService;
import de.fhkiel.webstore.data.Item;
import de.fhkiel.webstore.data.Payment;
import de.fhkiel.webstore.data.PaymentRow;
import de.fhkiel.webstore.utils.SessionHelper;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	private final String ITEM_SERVICE = "ItemService";
	private final String PAYMENT_SERVICE = "PaymentService";
	private final String SERVICE_NAME = "http://webservice.fhkiel.de/";
	private final String WSDL_LOCATION = "http://localhost:8080/ModernWebservice/services/";

	private ItemService itemService;
	private PaymentService paymentService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String redirect(Locale locale, Model model) throws Exception {
		logger.info("root was accessed, redirecting");

		URL itemServiceUrl = new URL( WSDL_LOCATION+ITEM_SERVICE+"?wsdl" );
		URL paymentServiceUrl = new URL( WSDL_LOCATION+PAYMENT_SERVICE+"?wsdl" );
		QName itemServiceName = new QName( SERVICE_NAME, ITEM_SERVICE+"ImplService" );
		QName paymentServiceName = new QName( SERVICE_NAME, PAYMENT_SERVICE+"ImplService" );
		itemService = Service.create( itemServiceUrl, itemServiceName ).getPort( ItemService.class );
		paymentService = Service.create( paymentServiceUrl, paymentServiceName ).getPort( PaymentService.class );

		return "redirect:/home";
	}

	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("homepage was accessed");

		try {
			model.addAttribute("items", itemService.listItem());
		} catch(Exception e) {
			model.addAttribute("error", "Server request failed");
			logger.error("Server request error", e);
		}

		return "home";
	}

	@RequestMapping(value = "/home/{id}", method = RequestMethod.GET)
	public String home(@PathVariable("id") Long id, HttpSession session, Locale locale, Model model) {
		logger.info("home with id ["+id+"] was accessed");

		SessionHelper.addItem(session, id);
		return "redirect:/home";
	}

	@RequestMapping(value = "/basket", method = RequestMethod.GET)
	public String basket(HttpSession session, Locale locale, Model model) {
		logger.info("basked was accessed");

		try {
			List<Item> items = itemService.listItem();
			HashMap<Long, Integer> itemIds = SessionHelper.getItems(session);
			List<Item> basket = new ArrayList<Item>();

			for ( Long itemId : itemIds.keySet() ) {
				for ( Item item : items ) {
					if ( item.getId().equals( itemId ) ) {
						item.setPrice( Math.round( (itemIds.get( itemId ) * item.getPrice())*100 )/100.0 );
						basket.add( item );
					}
				}
			}
			model.addAttribute("items", basket);
			model.addAttribute("amount", itemIds);
		} catch(Exception e) {
			model.addAttribute("error", "Server request failed");
			logger.error("Server request error", e);
		}

		return "basket";
	}

	@RequestMapping(value = "/basket/sub/{id}", method = RequestMethod.GET)
	public String basketSubstract(@PathVariable("id") Long id, HttpSession session, Locale locale) {
		logger.info("basket substract with id ["+id+"] was accessed");

		SessionHelper.subItem(session, id);
		return "redirect:/basket";
	}

	@RequestMapping(value = "/basket/add/{id}", method = RequestMethod.GET)
	public String basketAdd(@PathVariable("id") Long id, HttpSession session, Locale locale) {
		logger.info("basket add with id ["+id+"] was accessed");

		SessionHelper.addItem(session, id);
		return "redirect:/basket";
	}

	@RequestMapping(value = "/basket/rem/{id}", method = RequestMethod.GET)
	public String basketRemove(@PathVariable("id") Long id, HttpSession session, Locale locale) {
		logger.info("basket remove with id ["+id+"] was accessed");

		SessionHelper.removeItem(session, id);
		return "redirect:/basket";
	}

	@RequestMapping(value = "/payment", method = RequestMethod.GET)
	public String payment(HttpSession session, Locale locale, Model model) {
		logger.info("payment was accessed");
		Double total = 0.0;
		try {
			List<Item> items = itemService.listItem();
			HashMap<Long, Integer> itemIds = SessionHelper.getItems(session);
			List<Item> basket = new ArrayList<Item>();

			for ( Long itemId : itemIds.keySet() ) {
				for ( Item item : items ) {
					if ( item.getId().equals( itemId ) ) {
						item.setPrice( Math.round( (itemIds.get( itemId ) * item.getPrice())*100 )/100.0 );
						total += item.getPrice();
						basket.add( item );
					}
				}
			}
			model.addAttribute("items", basket);
			model.addAttribute("payment", new Payment());
			model.addAttribute("total", total);
			model.addAttribute("amount", itemIds);
		} catch(Exception e) {
			model.addAttribute("error", "Server request failed");
			logger.error("Server request error", e);
		}

		return "payment";
	}

	@RequestMapping( value = "/payment", method = RequestMethod.POST )
	public String submitPayment( Payment payment, Model model, HttpSession session ) {
		logger.info("payment was with submission ["+payment+"] was accessed");

		HashMap<Long, Integer> items = SessionHelper.getItems( session );

		Set<PaymentRow> paymentRows = new HashSet<PaymentRow>();
		for ( Long itemId : items.keySet() ) {
			PaymentRow paymentRow = new PaymentRow();
			paymentRow.setItemId( itemId );
			paymentRow.setCount( items.get( itemId ) );
			paymentRow.setPayment( payment );
			paymentRows.add( paymentRow );
		}
		payment.setPaymentRow( paymentRows );
		paymentService.addPayment( payment );

		if( SessionHelper.getItems( session ).isEmpty() ) {
			logger.debug( "session has expired" );
			return "redirect:/home";
		}
		
		SessionHelper.cleanItems( session );
		model.addAttribute("message", 
				"Items will arrive to "+payment.getAddress()+"<br />Thank you for buying");
		return "payment";
	}
}
